package wechat

import (
	"encoding/xml"
	"fmt"
	"github.com/silenceper/wechat/v2/officialaccount/context"
	"github.com/silenceper/wechat/v2/officialaccount/message"
	"github.com/silenceper/wechat/v2/util"
	"github.com/sirupsen/logrus"
	"micro-grpc-server/library/wechat/handlers"
	wechat "micro-grpc-server/services/wechat/proto"
	"strconv"
)

type customerMessage struct{}

// 这个玩意 在引入的包中只支持http访问
// 然而服务拿到的content是新建的 content.Background() 没有相应参数 让人头大
type RobotServer struct {
	handle handlers.HandleRequest
	// 怎么保证一次消息多返回时的顺序发送?
	messages chan *customerMessage
}

func NewRobotServer(handler handlers.HandleRequest) *RobotServer {
	server := &RobotServer{
		handle:   handler,
		messages: make(chan *customerMessage, 100),
	}
	server.handle = handler
	go server.consumeCustomerMsg()
	return server
}

// 消费客服消息
func (srv *RobotServer) consumeCustomerMsg() {
	fmt.Println("进入到消费的地方了")
	for msg := range srv.messages {
		go fmt.Println(msg)
	}
	fmt.Println("结束消费")
}

// 验证消息
func (srv *RobotServer) validateSignature(rq *wechat.RobotQuery, token string) bool {
	return rq.Signature == util.Signature(token, rq.Timestamp, rq.Nonce)
}

// 验证加密消息
func (srv *RobotServer) validateMessage(rq *wechat.WechatReplyRequest, ctx *context.Context) bool {
	if rq.Query.MsgSignature != util.Signature(ctx.Token, rq.Query.Timestamp, rq.Query.Nonce, rq.EncryptedXMLMsg.EncryptedMsg) {
		logrus.Debugf("validate failed token=%s signature=%s, timestamp=%s, nonce=%s", ctx.Token, rq.Query.Signature, rq.Query.Timestamp, rq.Query.Nonce)
		return false
	}
	var (
		rawXMLMsgBytes []byte
		err            error
	)
	rq.Append.Random, rawXMLMsgBytes, err = util.DecryptMsg(ctx.AppID, rq.EncryptedXMLMsg.EncryptedMsg, ctx.EncodingAESKey)
	if err != nil {
		return false
	}
	if err := xml.Unmarshal(rawXMLMsgBytes, &rq.Body); err != nil {
		return false
	}
	return true
}

// 验证签名
func (srv *RobotServer) validate(rq *wechat.WechatReplyRequest, ctx *context.Context) bool {
	if err := srv.assignmentAppend(rq); err != nil {
		return false
	}
	if !srv.validateSignature(rq.Query, ctx.Token) {
		logrus.Debugf("validate failed signature=%s, timestamp=%s, nonce=%s", rq.Query.Signature, rq.Query.Timestamp, rq.Query.Nonce)
		return false
	}
	return srv.validateMessage(rq, ctx)
}

// 给rq中的append赋值 在整个回复周期中 所有需求的参数应该在rq中
func (srv *RobotServer) assignmentAppend(rq *wechat.WechatReplyRequest) (err error) {
	rq.Append.Nonce = rq.Query.Nonce
	rq.Append.Openid = rq.Query.Openid
	rq.Append.Timestamp, err = strconv.ParseInt(rq.Query.Timestamp, 10, 32)
	return err
}

// 中转处理方法
func (srv *RobotServer) HandleRequest(rq *wechat.WechatReplyRequest, ch chan *message.Reply, ctx *context.Context) {
	// 验证未通过
	if !srv.validate(rq, ctx) {
		ch <- nil
		return
	}

	var r *message.Reply
	switch rq.Body.MsgType {
	case "text":
		r, _ = srv.handle.Text(rq.Body)
	case "image":
		r, _ = srv.handle.Image(rq.Body)
	case "voice":
		r, _ = srv.handle.Video(rq.Body)
	case "video":
		r, _ = srv.handle.Video(rq.Body)
	case "shortvideo":
		r, _ = srv.handle.ShortVideo(rq.Body)
	case "location":
		r, _ = srv.handle.Location(rq.Body)
	case "link":
		r, _ = srv.handle.Link(rq.Body)
	case "event":
		r, _ = srv.handleEventRequest(rq)
	default:
		logrus.Errorf("undefined wechat msgType -> %s", rq.Body.MsgType)
	}
	// 通道关闭证明超时了
	if _, closed := <-ch; closed {
		// TODO 这个地方用客服消息发送给用户
	} else {
		ch <- r
	}
	return
}

// 事件处理方法
func (srv *RobotServer) handleEventRequest(rq *wechat.WechatReplyRequest) (r *message.Reply, err error) {
	switch rq.Body.Event {
	case "subscribe":
		return srv.handle.Subscribe(rq.Body)
	case "unsubscribe":
		return srv.handle.UnSubscribe(rq.Body)
	case "SCAN":
		return srv.handle.Scan(rq.Body)
	case "LOCATION":
		return srv.handle.LocationEvent(rq.Body)
	case "CLICK":
		return srv.handle.Click(rq.Body)
	case "VIEW":
		return srv.handle.View(rq.Body)
	default:
		logrus.Errorf("undefined wechat event -> %s", rq.Body.MsgType)
	}
	return nil, nil
}
